package com.hp.shiro.shiroconfig;

import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {

	// 注入自定义的realm，告诉shiro如何获取用户信息来做登录或权限控制
	@Bean
	public Realm realm() {
		return new MyRealm();
	}

	//凭证匹配器（由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了）
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		// 设置用于匹配密码的CredentialsMatcher
		HashedCredentialsMatcher hashMatcher = new HashedCredentialsMatcher();
		hashMatcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
		//hashMatcher.setStoredCredentialsHexEncoded(true);// 存储散列后的密码是否为16进制
		hashMatcher.setHashIterations(1024);// 加密次数
		return hashMatcher;
	}

	// 权限管理，配置主要是Realm的管理认证
	@Bean
	public DefaultWebSecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(realm());
		return securityManager;
	}

	@Bean
	public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		/**
		 * setUsePrefix(false)用于解决一个奇怪的bug。在引入spring aop的情况下。
		 * 在@Controller注解的类的方法中加入@RequiresRole注解，会导致该方法无法映射请求，导致返回404。
		 * 加入这项配置能解决这个bug
		 */
		creator.setUsePrefix(true);// 网上的查询这里都设置为true,
		return creator;
	}

	// Filter工厂，设置对应的过滤条件和跳转条件
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		Map<String, String> map = new HashMap<String, String>();
		// 过滤静态资源
		map.put("/resources/**", "anon");
		// 过滤静态资源
		map.put("/error/**", "anon");
		map.put("/main/login", "anon");

		// 登出
		map.put("/logout", "logout");
		// 对所有用户认证
		map.put("/**", "authc");
		// 登录
		shiroFilterFactoryBean.setLoginUrl("/index.html");
		// 首页
		shiroFilterFactoryBean.setSuccessUrl("/main.html");
		// 错误页面，认证不通过跳转
		shiroFilterFactoryBean.setUnauthorizedUrl("/error/403.html");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
		return shiroFilterFactoryBean;
	}

	// 加入注解的使用，不加入这个注解不生效
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	/**
	 * shiro注解:
	 * 
	 * @RequiresGuest 只有游客可以访问
	 * @RequiresAuthentication 需要登录才能访问---->可以直接添加到类上
	 * @RequiresUser 已登录的用户或“记住我”的用户能访问
	 * @RequiresRoles 已登录的用户需具有指定的角色才能访问
	 * @RequiresPermissions 已登录的用户需具有指定的权限才能访问
	 */
}
